package com.xbh.management.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.nimbusds.jose.JOSEException;
import com.xbh.common.utils.RedisUtils;
import com.xbh.common.web.core.Result;
import com.xbh.management.entity.PayloadDTO;
import com.xbh.management.entity.SecurityUserVO;
import com.xbh.management.model.ManUser;
import com.xbh.management.utils.JwtUtilManagement;
import com.xbh.management.utils.ResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @program: management-center
 * @description: 认证过滤器
 * @author: 许宝华
 * @create: 2021-10-05 15:38
 */

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter {

    private static Logger log = LoggerFactory.getLogger(TokenLoginFilter.class);


    private JwtUtilManagement jwtUtilManagement;

    private RedisUtils redisUtils;

    private AuthenticationManager authenticationManager;

    private static String signatureAlgorithmSecret="abcdefghijklmnopqrstuvwxyz123456789";


    public TokenLoginFilter(JwtUtilManagement jwtUtilManagement, RedisUtils redisUtils, AuthenticationManager authenticationManager) {
        this.jwtUtilManagement = jwtUtilManagement;
        this.redisUtils = redisUtils;
        this.authenticationManager = authenticationManager;
        this.setPostOnly(false);
        log.info("认证过滤器，拦截到了登录请求登录请求");
        //   对/user/login中POST请求做拦截，校验表单中用户名密码
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/admin/user/login","POST"));
    }

    /**
     * 获取前台表单提交的用户名和密码
     * @param request
     * @param response
     * @return
     * @throws AuthenticationException
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        //获取表单提交过来的数据
        try {
            log.info("获取到了表单提交的数据");
            ManUser user = new ObjectMapper().readValue(request.getInputStream(), ManUser.class);
            log.info(user.toString());
            Authentication authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), new ArrayList<>()));
            return authenticate;
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException();
        }


    }

    /**
     * 认证通过之后
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        //认证成功，得到认证成功之后的用户信息
        log.info("认证成功");
        SecurityUserVO user = (SecurityUserVO) authResult.getPrincipal();
        //根据用户名生成token
        PayloadDTO payload = jwtUtilManagement.getPayload(user.getCurrentUserInfo());
        // 生成token
        String payloadJsonString = JSON.toJSONString(payload);
        String token;
        try {
            token = JwtUtilManagement.generateToken(payloadJsonString, signatureAlgorithmSecret);
            //把用户名称和用户权限列表存放到redis中
            redisUtils.set(user.getCurrentUserInfo().getUsername(),user.getPermissionValueList());
            //返回token
            Map<String,Object> userInfoAndToken=new HashMap<>();
            userInfoAndToken.put("userInfo",user.getCurrentUserInfo());
            userInfoAndToken.put("token",token);
            ResponseUtil.out(response, Result.result("000","login success",userInfoAndToken));
        } catch (JOSEException e) {
            e.printStackTrace();
        }
    }

    /**
     * 认证失败
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        log.info("认证失败");
        ResponseUtil.out(response, Result.result("445","captcha error",null));
    }
}
